package se.webbzon.oschi01.collision3d;

import java.util.ArrayList;
import java.util.Collection;

import javax.vecmath.Point3d;

public class CollisionEllipsoid3D extends CollisionModel3D {

	/*============================================================
	Constructors
	============================================================*/
	
	/** Creates a new collision ellipsoid with height, width and depth
	 * equal to 1. The center of the ellipsoid will be placed in the
	 * origin. The number of divisions will be equal to 18. **/
	public CollisionEllipsoid3D() {
		this(18);
	}
	
	/** Creates a new collision ellipsoid with height, width and depth
	 * equal to 1. The center of the ellipsoid will be placed in the
	 * origin. The number of divisions is given by the input. **/
	public CollisionEllipsoid3D(int divisions) {
		this(1,1,1,divisions);
	}
	
	/** Creates a new collision ellipsoid with a given height, width 
	 * and depth. The center of the ellipsoid will be placed in the
	 * origin. The number of divisions is given by the input. **/
	public CollisionEllipsoid3D(double width, double height, 
								double depth, int divisions) {
		super(createModel(width,height,depth,divisions));
	}
	
	/*============================================================
	Private Methods
	============================================================*/
	
	/** Creates the collision model. **/
	private static Collection<CollisionTriangle3D> createModel(	double width,
																double height,
																double depth,
																int divisions) {
		final double w = width/2, h = height/2, d = depth/2;
		final Point3d top = new Point3d(0,h,0);
		final Point3d bottom = new Point3d(0,-h,0);
		final Point3d p1 = new Point3d();
		final Point3d p2 = new Point3d();
		final Point3d p3 = new Point3d();
		ArrayList<CollisionTriangle3D> vertices = new ArrayList<CollisionTriangle3D>();
		
		final double dPhi = 2*Math.PI/divisions;
		final double dTheta = Math.PI/(divisions/2);
		// Shape the top and bottom of the ellipsoid
		for (int i = 0; i < divisions; i++) {
			final double phi = i * dPhi;
			// Top
			p1.set(	w*Math.sin(dTheta)*Math.cos(phi),
					h*Math.cos(dTheta),
					-d*Math.sin(dTheta)*Math.sin(phi));
			p2.set(	w*Math.sin(dTheta)*Math.cos(phi+dPhi),
					h*Math.cos(dTheta),
					-d*Math.sin(dTheta)*Math.sin(phi+dPhi));
			vertices.add(new CollisionTriangle3D(top,p1,p2));
			// Bottom
			p1.set(	w*Math.sin(Math.PI-dTheta)*Math.cos(phi),
					h*Math.cos(Math.PI-dTheta),
					-d*Math.sin(Math.PI-dTheta)*Math.sin(phi));
			p2.set(	w*Math.sin(Math.PI-dTheta)*Math.cos(phi+dPhi),
					h*Math.cos(Math.PI-dTheta),
					-d*Math.sin(Math.PI-dTheta)*Math.sin(phi+dPhi));
			vertices.add(new CollisionTriangle3D(bottom,p1,p2));
		}
		
		// Close the ellipsoid
		for (int i = 0; i < divisions; i++) {
			final double phi = i * dPhi;
			for (int j = 0; j < (divisions-4)/2; j++) {
				final double theta = (j+1) * dTheta;
				// Create diagonal corners of the square
				p1.set(	w*Math.sin(theta)*Math.cos(phi),
						h*Math.cos(theta),
						d*Math.sin(theta)*Math.sin(phi));
				p2.set(	w*Math.sin(theta+dTheta)*Math.cos(phi+dPhi),
						h*Math.cos(theta+dTheta),
						d*Math.sin(theta+dTheta)*Math.sin(phi+dPhi));
				// Create and add the collision square
				p3.set(	w*Math.sin(theta)*Math.cos(phi+dPhi),
						h*Math.cos(theta),
						d*Math.sin(theta)*Math.sin(phi+dPhi));
				vertices.add(new CollisionTriangle3D(p1,p2,p3));
				p3.set(	w*Math.sin(theta+dTheta)*Math.cos(phi),
						h*Math.cos(theta+dTheta),
						d*Math.sin(theta+dTheta)*Math.sin(phi));
				vertices.add(new CollisionTriangle3D(p1,p2,p3));
			}
		}
		
		return vertices;
	}
	
}
